package com.ming.job.xxljob.controller;

import com.ming.common.Options;
import com.ming.common.SortBy;
import com.ming.common.beetl.util.Result;
import com.ming.common.beetl.util.StrUtil;
import com.ming.common.xxljob.annotation.PermissionLimit;
import com.ming.common.xxljob.enums.RegistryConfig;
import com.ming.job.core.model.XxlJobRegistry;
import com.ming.job.core.util.I18nUtil;
import com.ming.job.xxljob.entity.XxlJobGroup;
import com.ming.job.xxljob.entity.XxlJobInfo;
import com.ming.job.xxljob.vo.XxlJobGroupVo;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.page.PageResult;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

@RestController
@RequestMapping("/xxljob/group")
public class IvyXxlJobGroupController {

    @Resource
    private SQLManager sqlManager;

    @PostMapping("/options")
    @PermissionLimit(limit = false)
    public Result<?> elOptions(@RequestBody(required = false) Map<String,Object> map) {
        LambdaQuery<XxlJobGroup> query = sqlManager.lambdaQuery(XxlJobGroup.class);
        List<XxlJobGroup> list = query.select(XxlJobGroup::getId,XxlJobGroup::getAppName,XxlJobGroup::getTitle);
        return Result.OK(list);
    }

    @PostMapping("/page")
    @PermissionLimit(limit = false)
    public Result<PageResult<XxlJobGroup>> page(@RequestBody XxlJobGroupVo vo){
        LambdaQuery<XxlJobGroup> lambdaQuery = sqlManager.lambdaQuery(XxlJobGroup.class);
        lambdaQuery.andLike(XxlJobGroup::getAppName, LambdaQuery.filterLikeEmpty(vo.getAppName()));
        lambdaQuery.andLike(XxlJobGroup::getTitle, LambdaQuery.filterLikeEmpty(vo.getTitle()));
        lambdaQuery.andEq(XxlJobGroup::getAddressType, LambdaQuery.filterEmpty(vo.getAddressType()));
        Options options = vo.getOptions();
        List<SortBy> sortBy = options.getSortBy();
        for (SortBy sort : sortBy) {
            if ("desc".equalsIgnoreCase(sort.getOrder())) {
                lambdaQuery.desc(StrUtil.camelToSnake(sort.getKey()));
            } else {
                lambdaQuery.asc(StrUtil.camelToSnake(sort.getKey()));
            }
        }
        PageResult<XxlJobGroup> page = lambdaQuery.page(options.getPage(), options.getItemsPerPage());
        return Result.OK(page);
    }

    @PostMapping("/add")
    @PermissionLimit(limit = false)
    public Result<?> add(@RequestBody XxlJobGroup xxlJobGroup){
        if (xxlJobGroup.getAppName()==null || xxlJobGroup.getAppName().trim().length()==0) {
            return Result.error(I18nUtil.getString("system_please_input")+"AppName");
        }
        if (xxlJobGroup.getAppName().length()<4 || xxlJobGroup.getAppName().length()>64) {
            return Result.error(I18nUtil.getString("jobgroup_field_appname_length"));
        }
        if (xxlJobGroup.getAppName().contains(">") || xxlJobGroup.getAppName().contains("<")) {
            return Result.error("AppName"+I18nUtil.getString("system_unvalid"));
        }
        if (xxlJobGroup.getTitle()==null || xxlJobGroup.getTitle().trim().length()==0) {
            return Result.error(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title"));
        }
        if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) {
            return Result.error(I18nUtil.getString("jobgroup_field_title")+I18nUtil.getString("system_unvalid"));
        }
        if (xxlJobGroup.getAddressType()!=0) {
            if (xxlJobGroup.getAddressList()==null || xxlJobGroup.getAddressList().trim().length()==0) {
                return Result.error(I18nUtil.getString("jobgroup_field_addressType_limit"));
            }
            if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) {
                return Result.error(I18nUtil.getString("jobgroup_field_registryList")+I18nUtil.getString("system_unvalid"));
            }

            String[] addresss = xxlJobGroup.getAddressList().split(",");
            for (String item: addresss) {
                if (item==null || item.trim().length()==0) {
                    return Result.error(I18nUtil.getString("jobgroup_field_registryList_unvalid"));
                }
            }
        }
        xxlJobGroup.setUpdateTime(new Date());
        return Result.insert(sqlManager.lambdaQuery(XxlJobGroup.class).insert(xxlJobGroup));
    }

    @PostMapping("/update")
    @PermissionLimit(limit = false)
    public Result<?> update(@RequestBody XxlJobGroup xxlJobGroup){
        if (xxlJobGroup.getAppName()==null || xxlJobGroup.getAppName().trim().length()==0) {
            return Result.error(I18nUtil.getString("system_please_input")+"AppName");
        }
        if (xxlJobGroup.getAppName().length()<4 || xxlJobGroup.getAppName().length()>64) {
            return Result.error(I18nUtil.getString("jobgroup_field_appname_length"));
        }
        if (xxlJobGroup.getTitle()==null || xxlJobGroup.getTitle().trim().length()==0) {
            return Result.error(I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title"));
        }
        if (xxlJobGroup.getAddressType() == 0) {
            // 0=自动注册
            List<String> registryList = findRegistryByAppName(xxlJobGroup.getAppName());
            String addressListStr = null;
            if (registryList!=null && !registryList.isEmpty()) {
                Collections.sort(registryList);
                addressListStr = "";
                for (String item:registryList) {
                    addressListStr += item + ",";
                }
                addressListStr = addressListStr.substring(0, addressListStr.length()-1);
            }
            xxlJobGroup.setAddressList(addressListStr);
        } else {
            // 1=手动录入
            if (xxlJobGroup.getAddressList()==null || xxlJobGroup.getAddressList().trim().length()==0) {
                return Result.error(I18nUtil.getString("jobgroup_field_addressType_limit"));
            }
            String[] addresss = xxlJobGroup.getAddressList().split(",");
            for (String item: addresss) {
                if (item==null || item.trim().length()==0) {
                    return Result.error(I18nUtil.getString("jobgroup_field_registryList_unvalid"));
                }
            }
        }
        xxlJobGroup.setUpdateTime(new Date());
        return Result.update(sqlManager.updateById(xxlJobGroup));
    }

    @PostMapping("/delete")
    @PermissionLimit(limit = false)
    public Result<?> delete(@RequestBody XxlJobGroup item){
        LambdaQuery<XxlJobInfo> query = sqlManager.lambdaQuery(XxlJobInfo.class);
        query.andEq(XxlJobInfo::getId, item.getId());
        long count = query.count();
        if (count > 0) {
            return Result.error(I18nUtil.getString("jobgroup_del_limit_0"));
        }
        LambdaQuery<XxlJobGroup> groupLambdaQuery = sqlManager.lambdaQuery(XxlJobGroup.class);
        long groupCount = groupLambdaQuery.count();
        if (groupCount == 1) {
            return Result.error(I18nUtil.getString("jobgroup_del_limit_1"));
        }
        LambdaQuery<XxlJobGroup> lambdaQuery = sqlManager.lambdaQuery(XxlJobGroup.class);
        lambdaQuery.andEq(XxlJobGroup::getId, item.getId());
        int i = lambdaQuery.delete();
        return Result.OK("删除成功",i);
    }

    @RequestMapping("/loadById")
    @PermissionLimit(limit = false)
    public Result<?> loadById(int id){
        LambdaQuery<XxlJobGroup> query = sqlManager.lambdaQuery(XxlJobGroup.class);
        query.andEq(XxlJobGroup::getId, id);
        XxlJobGroup jobGroup = query.single();
        if(jobGroup != null){
            return Result.OK(jobGroup);
        }
        return Result.error("未查询到该任务执行器");
    }

    private List<String> findRegistryByAppName(String appnameParam){
        HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
        List<XxlJobRegistry> list = sqlManager.execute(new SQLReady("SELECT * FROM xxl_job_registry AS t WHERE t.update_time > DATE_ADD(?,INTERVAL -? SECOND)",new Date(), RegistryConfig.DEAD_TIMEOUT),XxlJobRegistry.class);
        if (list != null) {
            for (XxlJobRegistry item: list) {
                if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
                    String appname = item.getRegistryKey();
                    List<String> registryList = appAddressMap.get(appname);
                    if (registryList == null) {
                        registryList = new ArrayList<String>();
                    }

                    if (!registryList.contains(item.getRegistryValue())) {
                        registryList.add(item.getRegistryValue());
                    }
                    appAddressMap.put(appname, registryList);
                }
            }
        }
        return appAddressMap.get(appnameParam);
    }
}
